package gui;

import enums.TestPanelEnum;
import enums.TextBundleEnum;
import enums.URLEnum;
import gui.filefilter.XMLFileFilter;
import gui.filefilter.XMLFileView;
import gui.other.Dimensions;
import gui.panel_new.evaluation.exeptions.ExerciseNotBuiltException;
import gui.panel_new.evaluation.exeptions.PunctuationZeroException;
import gui.panel_new.evaluation.student.*;
import internationalization.Internationalizer;
import j_util.Cronometer;
import j_util.Utiles;
import misc.BundlesProvider;
import model.eval.Test;
import model.eval.TestExcercise;
import org.jvnet.substance.SubstanceLookAndFeel;
import org.jvnet.substance.skin.SubstanceMistAquaLookAndFeel;
import org.jvnet.substance.skin.SubstanceModerateLookAndFeel;
import org.jvnet.substance.skin.SubstanceOfficeSilver2007LookAndFeel;
import org.jvnet.substance.skin.SubstanceSaharaLookAndFeel;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ResourceBundle;
/*

    This file is part of Logica-Logike.

    Logica-Logike is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation version 3 of the License.

    Logica-Logike is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Logica-Logike.  If not, see <http://www.gnu.org/licenses/>.

 */
/**
 * Extiende de JFrame; permite al usuario conectarse al servidor para recibir las evaluacions y resolverlas;
 *
 * @author Jose Martin Rozanec;
 */
public class ClientTestFrame {
    public static void main(String[] args) {

        Internationalizer.setSpanish();
        final ResourceBundle textBundle = BundlesProvider.getBundle(URLEnum.TEXT_BUNDLE);
        JFrame.setDefaultLookAndFeelDecorated(true);
        try {
            UIManager.setLookAndFeel(new SubstanceOfficeSilver2007LookAndFeel());
        } catch (Exception e) {
            System.out.println("Substance OfficeSilver2007 failed to initialize");
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                final Test test = new Test();
                final JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileFilter(new XMLFileFilter());
                fileChooser.setFileView(new XMLFileView());

                final Cronometer cronometer = new Cronometer();
                final CardLayout excercisesCardLayout = new CardLayout();
                final JPanel excercisesPanel = new JPanel(excercisesCardLayout);
                final JPanel exercisePanels[] = new JPanel[9];

                final JTabbedPane tabbedPane = new JTabbedPane();

                final JFrame mainFrame = new JFrame();
                JToolBar toolBar = new JToolBar();
                toolBar.setFloatable(false);
                toolBar.setVisible(true);

                final JLabel exerciseLabel = new JLabel(Utiles.createImageIcon(URLEnum.getReference(URLEnum.EJERCICIO_SERVER)));
//                final JLabel exerciseLabel = new JLabel(Utiles.createImageIcon(URLEnum.getReference(URLEnum.EJERCICIO_CLIENT)));
                exerciseLabel.setEnabled(false);

                //todo en la parte de conexion ver de colocar el logo y todo lo de about como relleno!
                final JLabel exerciseOverTotalLabel = new JLabel("::/::");

                final JProgressBar progressBar = new JProgressBar();
                final JCheckBox resolvedCheckBox = new JCheckBox(textBundle.getString(TextBundleEnum.RESUELTO.toString()));
                resolvedCheckBox.setEnabled(false);
                resolvedCheckBox.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        test.getCurrent().setResolved(resolvedCheckBox.isSelected());
                        progressBar.setValue(test.getResolvedTestsPercentage());
                        progressBar.setToolTipText("" + test.getResolvedTestsPercentage() + "% " +
                                textBundle.getString(TextBundleEnum.DE_LOS_EJERCICIOS_RESUELTOS.toString()));
                    }
                });

                final JButton previousButton = new JButton(Utiles.createImageIcon(URLEnum.getReference(URLEnum.ANTERIOR)));
                previousButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        saveCurrentData(test.getCurrent().getPanelEnum(), exercisePanels);//saves exercise data
                        TestExcercise exercise = test.previous();
                        excercisesCardLayout.show(excercisesPanel, exercise.getPanelEnum().toString());
                        ShowPanelsManager.setExercisePanelInfo(exercise, exercisePanels);
                        exerciseOverTotalLabel.setText("" + test.getCurrentExerciseNumber() + "/" + test.getTotalExcercises());
                        resolvedCheckBox.setSelected(exercise.isResolved());
                    }
                });
                previousButton.setEnabled(false);

                final JButton nextButton = new JButton(Utiles.createImageIcon(URLEnum.getReference(URLEnum.SIGUIENTE)));
                nextButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        saveCurrentData(test.getCurrent().getPanelEnum(), exercisePanels);//saves exercise data
                        TestExcercise excercise = test.next();
                        excercisesCardLayout.show(excercisesPanel, excercise.getPanelEnum().toString());
                        ShowPanelsManager.setExercisePanelInfo(excercise, exercisePanels);
                        exerciseOverTotalLabel.setText("" + test.getCurrentExerciseNumber() + "/" + test.getTotalExcercises());
                        resolvedCheckBox.setSelected(excercise.isResolved());
                    }
                });
                nextButton.setEnabled(false);

                final TestOverviewStudentPanel connectPanel = new TestOverviewStudentPanel(cronometer, tabbedPane,
                        excercisesPanel, test, exerciseOverTotalLabel, exercisePanels);
                connectPanel.auxSetConnectionValues();//todo delete

                OposicionEvaluationPanel oposicionPanel = new OposicionEvaluationPanel();
                SylogismViolationsPanel sylogismViolationsPanel =
                        new SylogismViolationsPanel();
                SylogismReducirModosPanel sylogismReducirModosPanel =
                        new SylogismReducirModosPanel();
                MChoicePanel mChoicePanel = new MChoicePanel();
                TruthTableEvaluationPanel truthTableEvaluationPanel = new TruthTableEvaluationPanel();
                VennStudentPanel vennPanel = new VennStudentPanel();
                SylogismAnalysisPanel sylogismAnalysisPanel = new SylogismAnalysisPanel();
                SylogismFromParameters sylogismFromParameters = new SylogismFromParameters();
                PolisilogismoFromParameters polisilogismoFromParameters =
                        new PolisilogismoFromParameters();

                exercisePanels[0] = oposicionPanel;
                exercisePanels[1] = sylogismViolationsPanel;
                exercisePanels[2] = sylogismReducirModosPanel;
                exercisePanels[3] = mChoicePanel;
                exercisePanels[4] = truthTableEvaluationPanel;
                exercisePanels[5] = vennPanel;
                exercisePanels[6] = sylogismAnalysisPanel;
                exercisePanels[7] = sylogismFromParameters;
                exercisePanels[8] = polisilogismoFromParameters;

                excercisesPanel.add(sylogismViolationsPanel, TestPanelEnum.VIOLACIONES_SILOGISMO.toString());
                excercisesPanel.add(oposicionPanel, TestPanelEnum.OPOSICION.toString());
                excercisesPanel.add(sylogismReducirModosPanel, TestPanelEnum.REDUCCION_MODOS.toString());
                excercisesPanel.add(mChoicePanel, TestPanelEnum.MULTIPLE_CHOICE.toString());
                excercisesPanel.add(truthTableEvaluationPanel, TestPanelEnum.TRUTH_TABLE.toString());
                excercisesPanel.add(vennPanel, TestPanelEnum.VENN.toString());
                excercisesPanel.add(sylogismAnalysisPanel, TestPanelEnum.ANALISIS_SILOGISMO.toString());
                excercisesPanel.add(sylogismFromParameters, TestPanelEnum.CREAR_SILOGISMO.toString());
                excercisesPanel.add(polisilogismoFromParameters, TestPanelEnum.CREAR_POLISILOGISMO.toString());

                tabbedPane.addTab(textBundle.getString(TextBundleEnum.CONNECTION.toString()), null, connectPanel);
                tabbedPane.addChangeListener(new ChangeListener() {
                    public void stateChanged(ChangeEvent e) {
                        if (((JTabbedPane) e.getSource()).getSelectedComponent().getClass().toString().equals("class gui.panel_new.evaluation.student.TestOverviewStudentPanel")) {
                            nextButton.setEnabled(false);
                            previousButton.setEnabled(false);
                            exerciseLabel.setEnabled(false);
                            resolvedCheckBox.setEnabled(false);
                        } else {
                            nextButton.setEnabled(true);
                            previousButton.setEnabled(true);
                            exerciseLabel.setEnabled(true);
                            resolvedCheckBox.setEnabled(true);
                        }
                        excercisesCardLayout.show(excercisesPanel, test.getCurrent().getPanelEnum().toString());
                        ShowPanelsManager.setExercisePanelInfo(test.getCurrent(), exercisePanels);
                        connectPanel.refreshTestOverview();
                        exerciseOverTotalLabel.setText("" + test.getCurrentExerciseNumber() + "/" + test.getTotalExcercises());
                    }
                });

//                toolBar.add(openButton);//todo ocupar espacio!
//                toolBar.add(saveAsButton);

//                JPanel panel = new JPanel();
//                panel.setBorder(BorderFactory.createMatteBorder(0,0,0,1,Color.GRAY));
//                panel.add(exerciseLabel);
//                panel.add(previousButton);
//                panel.add(exerciseOverTotalLabel);
//                panel.add(nextButton);
//                toolBar.add(panel);

                toolBar.add(exerciseLabel);
                toolBar.add(previousButton);
                toolBar.add(exerciseOverTotalLabel);
                toolBar.add(nextButton);
                JSeparator separator = new JSeparator(JSeparator.VERTICAL);
                separator.setPreferredSize(new Dimension(25, 25));
                toolBar.add(separator);

                JLabel cronometerLabel = new JLabel(textBundle.getString(TextBundleEnum.TIEMPO_RESTANTE.toString()));
//                cronometer.setLabelText(textBundle.getString(TextBundleEnum.TIEMPO_RESTANTE.toString()) + ": ");
                cronometer.setLabelText("");
                cronometer.setLabel(cronometerLabel);
                cronometer.setContainer(toolBar);
                cronometer.showTimeOnLabel(true);

                final JCheckBox cronometerCheckBox = new JCheckBox(textBundle.getString(TextBundleEnum.TIME.toString()) + ": ");
                cronometerCheckBox.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        cronometer.showTimeOnLabel(cronometerCheckBox.isSelected());
                    }
                });
                cronometerCheckBox.setSelected(true);

                toolBar.add(cronometerCheckBox);
                toolBar.add(cronometerLabel);

                JSeparator separator2 = new JSeparator(JSeparator.VERTICAL);
                separator.setPreferredSize(new Dimension(25, 25));
                toolBar.add(new JLabel("  "));
                toolBar.add(separator2);
                toolBar.add(resolvedCheckBox);
                toolBar.add(progressBar);

                JSeparator separator3 = new JSeparator(JSeparator.VERTICAL);
                separator.setPreferredSize(new Dimension(25, 25));
                toolBar.add(new JLabel("  "));
                toolBar.add(separator3);

//                toolBar.add(new JLabel(Utiles.createImageIcon(URLEnum.getReference(URLEnum.SPACE_OP))));
                toolBar.add(new JLabel(Utiles.createImageIcon(URLEnum.getReference(URLEnum.LOOK_FEEL))));

                JRadioButton office2007RadioButton = createLFRadioButton(mainFrame, new SubstanceOfficeSilver2007LookAndFeel(), 1);
                office2007RadioButton.setSelected(true);

                JRadioButton aquaRadioButton = createLFRadioButton(mainFrame, new SubstanceMistAquaLookAndFeel(), 2);

                JRadioButton saharaRadioButton = createLFRadioButton(mainFrame, new SubstanceSaharaLookAndFeel(), 3);

                JRadioButton moderateRadioButton = createLFRadioButton(mainFrame, new SubstanceModerateLookAndFeel(), 4);

                ButtonGroup radioButtonGroup = new ButtonGroup();
                radioButtonGroup.add(office2007RadioButton);
                radioButtonGroup.add(aquaRadioButton);
                radioButtonGroup.add(saharaRadioButton);
                radioButtonGroup.add(moderateRadioButton);

                toolBar.add(office2007RadioButton);
                toolBar.add(aquaRadioButton);
                toolBar.add(saharaRadioButton);
                toolBar.add(moderateRadioButton);

                mainFrame.add(toolBar, BorderLayout.NORTH);
                mainFrame.add(tabbedPane);

                mainFrame.setSize(700, Dimensions.FRAME_HEIGHT);
                mainFrame.setTitle(textBundle.getString(TextBundleEnum.LOGICA.toString()) + " " +
                        textBundle.getString(TextBundleEnum.VERSION_NUMERO.toString()));
                mainFrame.setIconImage(Utiles.createImageIcon(URLEnum.getReference(URLEnum.LOGICA_ICON)).getImage());
                mainFrame.setResizable(false);

                switch (readLookAndFeelConfig()) {
                    case 2:
                        setLookAndFeel(aquaRadioButton, new SubstanceMistAquaLookAndFeel());
                        break;
                    case 3:
                        setLookAndFeel(saharaRadioButton, new SubstanceSaharaLookAndFeel());
                        break;
                    case 4:
                        setLookAndFeel(moderateRadioButton, new SubstanceModerateLookAndFeel());
                        break;
                }

                mainFrame.setVisible(true);
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
        });
    }

    /**
     * Escribe un archivo de configuracion en el que especifica el look and feel usado;
     *
     * @param lookAndFeel;
     */
    public static void writeLookAndFeelConfig(int lookAndFeel) {
        try {
            RandomAccessFile configFile = new RandomAccessFile(URLEnum.getReference(URLEnum.CONFIG_FILE), "rw");
            configFile.writeInt(lookAndFeel);
            configFile.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Lee el archivo de configuracion y establece el look & feel utilizado por ultima vez;
     *
     * @return int - look and feel;
     */
    public static int readLookAndFeelConfig() {
        try {
            RandomAccessFile configFile = new RandomAccessFile(URLEnum.getReference(URLEnum.CONFIG_FILE), "rw");
            return configFile.readInt();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            writeLookAndFeelConfig(1);
        }
        return -1;
    }

    /**
     * Crea un radioButton cuya seleccion cambia el look and feel al especificado;
     *
     * @param frame;
     * @param lookAndFeel;
     * @param lookAndFeelID;
     * @return JRadioButton;
     */
    private static JRadioButton createLFRadioButton(final JFrame frame, final SubstanceLookAndFeel lookAndFeel, final int lookAndFeelID) {
        JRadioButton radioButton = new JRadioButton();
        radioButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    UIManager.setLookAndFeel(lookAndFeel);
                    frame.repaint();
                    writeLookAndFeelConfig(lookAndFeelID);
                } catch (UnsupportedLookAndFeelException e1) {
                    System.out.println("Failed " + lookAndFeel.getDescription());
                }
            }
        });
        return radioButton;
    }

    /**
     * Permite setear el look and feel;
     *
     * @param radioButton;
     * @param lookAndFeel;
     */
    private static void setLookAndFeel(JRadioButton radioButton, SubstanceLookAndFeel lookAndFeel) {
        radioButton.setSelected(true);
        try {
            UIManager.setLookAndFeel(lookAndFeel);
        } catch (UnsupportedLookAndFeelException e1) {
            System.out.println("Failed " + lookAndFeel.getDescription());
        }
    }

    public static void saveCurrentData(TestPanelEnum currentPanelEnum, JPanel[] panels) {
        try {
            switch (currentPanelEnum) {
                case VIOLACIONES_SILOGISMO:
                    SylogismViolationsPanel sylogismViolationsPanel = (SylogismViolationsPanel) panels[1];

                    sylogismViolationsPanel.getExercise();
                    break;
                case REDUCCION_MODOS:
                    SylogismReducirModosPanel sylogismReducirModosPanel = (SylogismReducirModosPanel) panels[2];
                    sylogismReducirModosPanel.getExercise();
                    break;
                case MULTIPLE_CHOICE:
                    MChoicePanel mChoicePanel = (MChoicePanel) panels[3];
                    mChoicePanel.getExercise();
                    break;
                case OPOSICION:
                    OposicionEvaluationPanel oposicionEvaluationPanel = (OposicionEvaluationPanel) panels[0];
                    oposicionEvaluationPanel.getExercise();
                    break;
                case TRUTH_TABLE:
                    TruthTableEvaluationPanel truthTableEvaluationPanel = (TruthTableEvaluationPanel) panels[4];
                    truthTableEvaluationPanel.getExercise();
                    break;
                case VENN:
                    VennStudentPanel vennPanel = (VennStudentPanel) panels[5];
                    vennPanel.getExercise();
                    break;
                case ANALISIS_SILOGISMO:
                    SylogismAnalysisPanel sylogismAnalysisPanel = (SylogismAnalysisPanel) panels[6];
                    sylogismAnalysisPanel.getExercise();
                    break;
                case CREAR_SILOGISMO:
                    SylogismFromParameters sylogismFromParameters = (SylogismFromParameters) panels[7];
                    sylogismFromParameters.getExercise();
                    break;
                case CREAR_POLISILOGISMO:
                    PolisilogismoFromParameters polisilogismoFromParameters =
                            (PolisilogismoFromParameters) panels[8];
                    polisilogismoFromParameters.getExercise();
                    break;
            }
        } catch (ExerciseNotBuiltException e) {
            e.printStackTrace();
        } catch (PunctuationZeroException e) {
            e.printStackTrace();
        }
    }
}
